import java.net.*;
import java.io.*;
import java.util.*;



public class Server
{
    public int port = 1337;
    public ConnectionWorker[] connections;
    public Stack<MCMASServerData> seedStates;
    public Boolean foundCEX;
    public Vector<MCMASClientData> returnedClientData;

    public class ConnectionWorker extends Thread
    {
        public Connection connection;

        public ConnectionWorker(Socket socket)
        {
            connection = new Connection(socket);
        }

        public void run()
        { 
            try
            {
                while (seedStates.size() > 0 && !foundCEX)
                {
                    MCMASServerData serverData;
                    synchronized (seedStates)
                    {
                        serverData = seedStates.pop();
                    }
                    connection.objOut.writeObject(serverData);

                    MCMASClientData temp = (MCMASClientData) connection.objIn.readObject();
                    System.out.println(temp.seedState + "," + temp.memoryUsed + "," + temp.statesExplored + "," + temp.cexFound);
                    synchronized (returnedClientData)
                    {
                        returnedClientData.add(temp);
                    }
                    
                    if (temp.cexFound)
                    {
                        synchronized (foundCEX)
                        {
                            foundCEX = true;
                        }
                        break;
                    }


                }
                System.out.println(hashCode() + " Finished");
            }
            catch (Exception e)
            {
                System.out.println("Fail");
                System.out.println("Exception: " + e);
                e.printStackTrace();
            }
        }
    }

    public Server(int clientcount)
    {
        String file = "3_7_W.ispl"; 
        MCMASClientData mcmasClientData = new MCMASClientData();
        MCMASServerData mcmasServerData = new MCMASServerData();
        mcmasServerData.isplFile = file;
        boolean seeds = MCMASParser.MCMASMasterParser(mcmasServerData, mcmasClientData);

        if (!seeds)
        {
            if (mcmasClientData.cexFound)
            {
                System.out.println("FALSE");
            }
            else
            {
                System.out.println("TRUE");
            }
            System.exit(0);
        }
        //System.out.println(mcmasServerData.totalSeeds);
        
        seedStates = new Stack<MCMASServerData>();
        returnedClientData = new Vector<MCMASClientData>();
        foundCEX = new Boolean(false);

        for (int i = 0; i < mcmasServerData.totalSeeds; i++)
        {
            String seedFile = new Formatter().format("state_%04d.out",i).toString();
            MCMASServerData tempData = new MCMASServerData();
            tempData.isplFile = mcmasServerData.isplFile;
            tempData.directory = mcmasServerData.directory;
            tempData.totalSeeds = mcmasServerData.totalSeeds;
            tempData.seedState = seedFile;
            seedStates.push(tempData);
        }

        System.out.println(mcmasServerData.directory + seedStates.peek().seedState);

        try
        {
            ServerSocket serverSocket = new ServerSocket(port);
            System.out.println("We have socket");
            connections = new ConnectionWorker[clientcount];
            //serverSocket.setSoTimeout(1000);

            for (int i = 0; i < clientcount; ++i)
            {
                try
                {
                    Socket temp = serverSocket.accept();
                    connections[i] = new ConnectionWorker(temp);
                    connections[i].start();
                    System.out.println("Client " + i + " connected");
                }
                catch (Exception e) { break; }
            }
            
            while (seedStates.size() > 0 && !foundCEX)
            { 
                {
                    Thread.sleep(100);
                }
            }

            if (foundCEX)
            {
                    for (int i = 0; i < connections.length; ++i)
                    {
                        connections[i] = null;
                    }

                    System.out.println("FALSE");
            }
            else
            {
                System.out.println("TRUE");
            }

            int maxMem = 0;
            int maxStates = 0;
            int totalStates = 0;
            for (int i = 0; i < returnedClientData.size(); i++)
            {
                MCMASClientData data = returnedClientData.get(i);
                if (data.memoryUsed > maxMem) maxMem = data.memoryUsed;
                if (data.statesExplored > maxStates) maxStates = data.statesExplored;
                totalStates += data.statesExplored;
            }

            System.out.println("Server States: " + mcmasClientData.statesExplored);
            System.out.println("Server Memory: " + mcmasClientData.memoryUsed);

            System.out.println("Client Max States: " + maxStates);
            System.out.println("Client Max Memory: " + maxMem);
            System.out.println("Client Total States: " + totalStates);

            serverSocket.close();
        }
        catch (Exception e)
        {
            System.out.println("Fail");
            System.out.println("Exception: " + e);
            e.printStackTrace();
        }
    }

    public static void main(String args[])
    {
        Server server = new Server(3);
        System.exit(0);
    }
}
